using System;
using System.Collections.Generic;

namespace Glue.Internals.Verification
{
    internal class RelationsVerification<LeftType,RightType> : IRelationsVerification
    {
        private readonly Mapping<LeftType, RightType> mapping;
        private readonly ObjectMemberFactory objectMemberFactory;


        public RelationsVerification(Mapping<LeftType, RightType> mapping, ObjectMemberFactory objectMemberFactory)
        {
            this.mapping = mapping;
            this.objectMemberFactory = objectMemberFactory;
        }

        public void AssertAllPropertiesRelated<T>()
        {
            if (typeof(T) == typeof(LeftType))
                AssertAllPropertiesRelated(typeof(LeftType), mapping.Relations.IsRelatedTowardsOnLeftSide, mapping.Ignored.ContainsLeftSide);
            else if (typeof(T) == typeof(RightType))
                AssertAllPropertiesRelated(typeof(RightType), mapping.Relations.IsRelatedTowardsOnRightSide, mapping.Ignored.ContainsRightSide);
            else
                throw new GlueException("Failed to assert Properties on type '"+typeof(T).Name+"'. You must send in either '"+typeof(LeftType).Name+"' or '"+typeof(RightType).Name+"'");
        }

        private void AssertAllPropertiesRelated(Type type, Func<IObjectMember, bool> relationsContains, Func<IObjectMember, bool> ignoredContains)
        {
            var unrelatedProperties = new List<String>();
            foreach (var member in objectMemberFactory.GetObjectMembers(type))
            {
                if (!ignoredContains(member) && !relationsContains(member) && member.CanSetValues)
                    unrelatedProperties.Add(member.Name);
            }
            if (unrelatedProperties.Count > 0)
                throw new GlueException("Not all properties are related (or ignored) in "+type.GetReadableName()+": " + GetNames(unrelatedProperties));
        }

        private String GetNames(List<string> members)
        {
            return String.Join(",", members.ToArray());
            var errorMessage = "";
            foreach (var member in members)
            {
                errorMessage += member + ", ";
            }
            return errorMessage.Substring(0, errorMessage.Length - 1);
        }
    }
}